// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`functionImplementationErrors.ts 1`] = `
// @allowUnreachableCode: true

// FunctionExpression with no return type annotation with multiple return statements with unrelated types
var f1 = function () {
    return '';
    return 3;
};
var f2 = function x() {
    return '';
    return 3;
};
var f3 = () => {
    return '';
    return 3;
};

// FunctionExpression with no return type annotation with return branch of number[] and other of string[]
var f4 = function () {
    if (true) {
        return [''];
    } else {
        return [1];
    }
}

// Function implementation with non -void return type annotation with no return
function f5(): number {
}

var m;
// Function signature with parameter initializer referencing in scope local variable
function f6(n = m) {
    var m = 4;
}

// Function signature with initializer referencing other parameter to the right
function f7(n = m, m?) {
}

// FunctionExpression with non -void return type annotation with a throw, no return, and other code
// Should be error but isn't
undefined === function (): number {
    throw undefined;
    var x = 4;
};

class Base { private x; }
class AnotherClass { private y; }
class Derived1 extends Base { private m; }
class Derived2 extends Base { private n; }
function f8() {
    return new Derived1();
    return new Derived2();    
}
var f9 = function () {
    return new Derived1();
    return new Derived2();
};
var f10 = () => {
    return new Derived1();
    return new Derived2();
};
function f11() {
    return new Base();
    return new AnotherClass();
}
var f12 = function () {
    return new Base();
    return new AnotherClass();
};
var f13 = () => {
    return new Base();
    return new AnotherClass();
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @allowUnreachableCode: true

// FunctionExpression with no return type annotation with multiple return statements with unrelated types
var f1 = function() {
  return "";
  return 3;
};
var f2 = function x() {
  return "";
  return 3;
};
var f3 = () => {
  return "";
  return 3;
};

// FunctionExpression with no return type annotation with return branch of number[] and other of string[]
var f4 = function() {
  if (true) {
    return [""];
  } else {
    return [1];
  }
};

// Function implementation with non -void return type annotation with no return
function f5(): number {}

var m;
// Function signature with parameter initializer referencing in scope local variable
function f6(n = m) {
  var m = 4;
}

// Function signature with initializer referencing other parameter to the right
function f7(n = m, m?) {}

// FunctionExpression with non -void return type annotation with a throw, no return, and other code
// Should be error but isn't
undefined ===
  function(): number {
    throw undefined;
    var x = 4;
  };

class Base {
  private x;
}
class AnotherClass {
  private y;
}
class Derived1 extends Base {
  private m;
}
class Derived2 extends Base {
  private n;
}
function f8() {
  return new Derived1();
  return new Derived2();
}
var f9 = function() {
  return new Derived1();
  return new Derived2();
};
var f10 = () => {
  return new Derived1();
  return new Derived2();
};
function f11() {
  return new Base();
  return new AnotherClass();
}
var f12 = function() {
  return new Base();
  return new AnotherClass();
};
var f13 = () => {
  return new Base();
  return new AnotherClass();
};

`;

exports[`functionImplementations.ts 1`] = `
// @allowUnreachableCode: true

// FunctionExpression with no return type annotation and no return statement returns void
var v: void = function () { } ();

// FunctionExpression f with no return type annotation and directly references f in its body returns any
var a: any = function f() {
    return f;
};
var a: any = function f() {
    return f();
};

// FunctionExpression f with no return type annotation and indirectly references f in its body returns any
var a: any = function f() {
    var x = f;
    return x;
};

// Two mutually recursive function implementations with no return type annotations
function rec1() {
    return rec2();
}
function rec2() {
    return rec1();
}
var a = rec1();
var a = rec2();

// Two mutually recursive function implementations with return type annotation in one
function rec3(): number {
    return rec4();
}
function rec4() {
    return rec3();
}
var n: number;
var n = rec3();
var n = rec4();

// FunctionExpression with no return type annotation and returns a number
var n = function () {
    return 3;
} ();

// FunctionExpression with no return type annotation and returns null
var nu = null;
var nu = function () {
    return null;
} ();

// FunctionExpression with no return type annotation and returns undefined
var un = undefined;
var un = function () {
    return undefined;
} ();

// FunctionExpression with no return type annotation and returns a type parameter type
var n = function <T>(x: T) {
    return x;
} (4);

// FunctionExpression with no return type annotation and returns a constrained type parameter type
var n = function <T extends {}>(x: T) {
    return x;
} (4);

// FunctionExpression with no return type annotation with multiple return statements with identical types
var n = function () {
    return 3;
    return 5;
}();

// Otherwise, the inferred return type is the first of the types of the return statement expressions
// in the function body that is a supertype of each of the others, 
// ignoring return statements with no expressions.
// A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others.
// FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns
class Base { private m; }
class Derived extends Base { private q; }
var b: Base;
var b = function () {
    return new Base(); return new Derived();
} ();

// FunctionExpression with no return type annotation with multiple return statements with one a recursive call
var a = function f() {
    return new Base(); return new Derived(); return f(); // ?
} ();

// FunctionExpression with non -void return type annotation with a single throw statement
undefined === function (): number {
    throw undefined;
};

// Type of 'this' in function implementation is 'any'
function thisFunc() {
    var x = this;
    var x: any;
}

// Function signature with optional parameter, no type annotation and initializer has initializer's type
function opt1(n = 4) {
    var m = n;
    var m: number;
}

// Function signature with optional parameter, no type annotation and initializer has initializer's widened type
function opt2(n = { x: null, y: undefined }) {
    var m = n;
    var m: { x: any; y: any };
}

// Function signature with initializer referencing other parameter to the left
function opt3(n: number, m = n) {
    var y = m;
    var y: number;
}

// Function signature with optional parameter has correct codegen 
// (tested above)

// FunctionExpression with non -void return type annotation return with no expression
function f6(): number {
    return;
}

class Derived2 extends Base { private r: string; }
class AnotherClass { private x }
// if f is a contextually typed function expression, the inferred return type is the union type
// of the types of the return statement expressions in the function body, 
// ignoring return statements with no expressions.
var f7: (x: number) => string | number = x => { // should be (x: number) => number | string
    if (x < 0) { return x; }
    return x.toString();
}
var f8: (x: number) => any = x => { // should be (x: number) => Base
    return new Base();
    return new Derived2();
}
var f9: (x: number) => any = x => { // should be (x: number) => Base
    return new Base();
    return new Derived();
    return new Derived2();
}
var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1
    return new Derived();
    return new Derived2();
}
var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass
    return new Base();
    return new AnotherClass();
}
var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass
    return new Base();
    return; // should be ignored
    return new AnotherClass();
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @allowUnreachableCode: true

// FunctionExpression with no return type annotation and no return statement returns void
var v: void = (function() {})();

// FunctionExpression f with no return type annotation and directly references f in its body returns any
var a: any = function f() {
  return f;
};
var a: any = function f() {
  return f();
};

// FunctionExpression f with no return type annotation and indirectly references f in its body returns any
var a: any = function f() {
  var x = f;
  return x;
};

// Two mutually recursive function implementations with no return type annotations
function rec1() {
  return rec2();
}
function rec2() {
  return rec1();
}
var a = rec1();
var a = rec2();

// Two mutually recursive function implementations with return type annotation in one
function rec3(): number {
  return rec4();
}
function rec4() {
  return rec3();
}
var n: number;
var n = rec3();
var n = rec4();

// FunctionExpression with no return type annotation and returns a number
var n = (function() {
  return 3;
})();

// FunctionExpression with no return type annotation and returns null
var nu = null;
var nu = (function() {
  return null;
})();

// FunctionExpression with no return type annotation and returns undefined
var un = undefined;
var un = (function() {
  return undefined;
})();

// FunctionExpression with no return type annotation and returns a type parameter type
var n = (function<T>(x: T) {
  return x;
})(4);

// FunctionExpression with no return type annotation and returns a constrained type parameter type
var n = (function<T extends {}>(x: T) {
  return x;
})(4);

// FunctionExpression with no return type annotation with multiple return statements with identical types
var n = (function() {
  return 3;
  return 5;
})();

// Otherwise, the inferred return type is the first of the types of the return statement expressions
// in the function body that is a supertype of each of the others,
// ignoring return statements with no expressions.
// A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others.
// FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns
class Base {
  private m;
}
class Derived extends Base {
  private q;
}
var b: Base;
var b = (function() {
  return new Base();
  return new Derived();
})();

// FunctionExpression with no return type annotation with multiple return statements with one a recursive call
var a = (function f() {
  return new Base();
  return new Derived();
  return f(); // ?
})();

// FunctionExpression with non -void return type annotation with a single throw statement
undefined ===
  function(): number {
    throw undefined;
  };

// Type of 'this' in function implementation is 'any'
function thisFunc() {
  var x = this;
  var x: any;
}

// Function signature with optional parameter, no type annotation and initializer has initializer's type
function opt1(n = 4) {
  var m = n;
  var m: number;
}

// Function signature with optional parameter, no type annotation and initializer has initializer's widened type
function opt2(n = { x: null, y: undefined }) {
  var m = n;
  var m: { x: any; y: any };
}

// Function signature with initializer referencing other parameter to the left
function opt3(n: number, m = n) {
  var y = m;
  var y: number;
}

// Function signature with optional parameter has correct codegen
// (tested above)

// FunctionExpression with non -void return type annotation return with no expression
function f6(): number {
  return;
}

class Derived2 extends Base {
  private r: string;
}
class AnotherClass {
  private x;
}
// if f is a contextually typed function expression, the inferred return type is the union type
// of the types of the return statement expressions in the function body,
// ignoring return statements with no expressions.
var f7: (x: number) => string | number = x => {
  // should be (x: number) => number | string
  if (x < 0) {
    return x;
  }
  return x.toString();
};
var f8: (x: number) => any = x => {
  // should be (x: number) => Base
  return new Base();
  return new Derived2();
};
var f9: (x: number) => any = x => {
  // should be (x: number) => Base
  return new Base();
  return new Derived();
  return new Derived2();
};
var f10: (x: number) => any = x => {
  // should be (x: number) => Derived | Derived1
  return new Derived();
  return new Derived2();
};
var f11: (x: number) => any = x => {
  // should be (x: number) => Base | AnotherClass
  return new Base();
  return new AnotherClass();
};
var f12: (x: number) => any = x => {
  // should be (x: number) => Base | AnotherClass
  return new Base();
  return; // should be ignored
  return new AnotherClass();
};

`;

exports[`functionOverloadCompatibilityWithVoid01.ts 1`] = `
function f(x: string): number;
function f(x: string): void {
    return;
} 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function f(x: string): number;
function f(x: string): void {
  return;
}

`;

exports[`functionOverloadCompatibilityWithVoid02.ts 1`] = `
function f(x: string): void;
function f(x: string): number {
    return 0;
} 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function f(x: string): void;
function f(x: string): number {
  return 0;
}

`;

exports[`functionOverloadCompatibilityWithVoid03.ts 1`] = `
function f(x: string): void;
function f(x: string): void {
    return;
} 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function f(x: string): void;
function f(x: string): void {
  return;
}

`;

exports[`functionOverloadErrorsSyntax.ts 1`] = `
//Function overload signature with optional parameter followed by non-optional parameter
function fn4a(x?: number, y: string);
function fn4a() { }

function fn4b(n: string, x?: number, y: string);
function fn4b() { }

//Function overload signature with rest param followed by non-optional parameter
function fn5(x: string, ...y: any[], z: string);
function fn5() { }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Function overload signature with optional parameter followed by non-optional parameter
function fn4a(x?: number, y: string);
function fn4a() {}

function fn4b(n: string, x?: number, y: string);
function fn4b() {}

//Function overload signature with rest param followed by non-optional parameter
function fn5(x: string, ...y: any[], z: string);
function fn5() {}

`;

exports[`functionTypeTypeParameters.ts 1`] = `
type FuncWithTypeParameter = <T, P>() => {};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type FuncWithTypeParameter = <T, P>() => {};

`;

exports[`parameterInitializersForwardReferencing.ts 1`] = `
function left(a, b = a, c = b) {
    a;
    b;
}

function right(a = b, b = a) {
    a;
    b;
}

function right2(a = b, b = c, c = a) {
    a;
    b;
    c;
}

function inside(a = b) {
    var b;
}

function outside() {
    var b;
    function inside(a = b) { // Still an error because b is declared inside the function
        var b;
    }
}

function defaultArgFunction(a = function () { return b; }, b = 1) { }
function defaultArgArrow(a = () => () => b, b = 3) { }

class C {
    constructor(a = b, b = 1) { }
    method(a = b, b = 1) { }
}

// Function expressions
var x = (a = b, b = c, c = d) => { var d; };

// Should not produce errors - can reference later parameters if they occur within a function expression initializer.
function f(a, b = function () { return c; }, c = b()) {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function left(a, b = a, c = b) {
  a;
  b;
}

function right(a = b, b = a) {
  a;
  b;
}

function right2(a = b, b = c, c = a) {
  a;
  b;
  c;
}

function inside(a = b) {
  var b;
}

function outside() {
  var b;
  function inside(a = b) {
    // Still an error because b is declared inside the function
    var b;
  }
}

function defaultArgFunction(
  a = function() {
    return b;
  },
  b = 1
) {}
function defaultArgArrow(a = () => () => b, b = 3) {}

class C {
  constructor(a = b, b = 1) {}
  method(a = b, b = 1) {}
}

// Function expressions
var x = (a = b, b = c, c = d) => {
  var d;
};

// Should not produce errors - can reference later parameters if they occur within a function expression initializer.
function f(
  a,
  b = function() {
    return c;
  },
  c = b()
) {}

`;
